/*
 * smart_home.cpp
 *
 * Copyright (c) 2012-2012 Baghdasaryan Andrew (relfock at gmail dot com)
 */
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <string>
#include <iostream>

#include "helper.hpp"
#include "udp_server.hpp"
#include "tcp_server.hpp"
#include "config_parser.hpp"

#define TTY_CONF_NAME "tty.conf"
#define XML_CONFIG_NAME "config.xml"

/* tty-fd-mutex map */
std::map<std::string,Serial_info> port_map;

/* global_id objects map */
std::map<std::string, Base*> gids;

/* global_id per class map */
std::map<std::string, Base> vars;
std::map<std::string, Mode> modes;
std::map<std::string, Panel> panels;
std::map<std::string, Sensor> sensors;
std::map<std::string, Command> commands;
std::map<std::string, Timer> user_timers;
std::map<std::string, Device> other_devices;
std::map<std::string, Gsm> gsm_cmds;

/* Main entry point of the Smart home daemon. */
int main(int argc, char **argv)
{   
    try {
        /* Register signal handlers. */

        /*
         * Fork the process and have the parent exit. If the process was started
         * from a shell, this returns control to the user. Forking a new process is
         * also a prerequisite for the subsequent call to setsid().
         */
        //if (pid_t pid = fork()) {
        //    if (pid > 0) {
        //        exit(0);
        //    }
        //    else {
        //        syslog(LOG_ERR | LOG_USER, "First fork failed: %m");
        //        return 1;
        //    }
        //}

        //setsid();
        //chdir("/");
        //umask(0);

        ///* A second fork ensures the process cannot acquire a controlling terminal. */
        //if (pid_t pid = fork()) {
        //    if (pid > 0) {
        //        exit(0);
        //    }
        //    else {
        //        syslog(LOG_ERR | LOG_USER, "Second fork failed: %m");
        //        return 1;
        //    }
        //}

        ///*
        // * Close the standard streams. This decouples the daemon from the terminal
        // * that started it.
        // */
        //close(0);
        //close(1);
        //close(2);

        ///* We don't want the daemon to have any standard input. */
        //if (open("/dev/null", O_RDONLY) < 0) {
        //    syslog(LOG_ERR | LOG_USER, "Unable to open /dev/null: %m");
        //    return 1;
        //}

        ///* Send standard output to a log file. */
        //const char* output = "/var/log/smart_home";
        //const int flags = O_WRONLY | O_CREAT | O_APPEND;
        //const mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
        //if (open(output, flags, mode) < 0) {
        //    syslog(LOG_ERR | LOG_USER, "Unable to open output file %s: %m", output);
        //    return 1;
        //}

        ///* Also send standard error to the same log file. */
        //if (dup(1) < 0) {
        //    syslog(LOG_ERR | LOG_USER, "Unable to dup output descriptor: %m");
        //    return 1;
        //}

        /* Parsing config.xml configuration file. */
        parse_config(XML_CONFIG_NAME);

        /* Parsing tty.conf serial config file */
        //parse_serial_config(TTY_CONF_NAME);

        //init_gsm();

        init_and_start_core();

        /* Initialize UDP/TCP servers on 2323/2324 ports. */
        init_udp_server();
        logger("Successfully initialized UDP server on port 2323.\n");

        init_tcp_server();
        logger("Successfully initialized TCP server on port 2324.\n");

        // syslog(LOG_INFO | LOG_USER, "Smart Home server started");
        logger("Smart Home server started: PID = %d\n" , getpid());

        for(;;){
            sleep(300);
        }

        /* syslog(LOG_INFO | LOG_USER, "Smart Home server stopped"); */
        logger("Smart Home server stopped\n");
    }
    catch (std::exception& e) {
        /*
         *syslog(LOG_ERR | LOG_USER, "Exception: %s", e.what());
         */
        logger("Exception: %s\n", e.what());
    }
}
